package com.java.model.singleton;

import org.springframework.objenesis.instantiator.util.UnsafeUtils;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class TestSingleton {
    public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException, IOException, ClassNotFoundException {
//        HungrySingleton.otherMethod();
        System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>");
//        System.out.println(HungrySingleton.getInstance());
//        System.out.println(HungrySingleton.getInstance());
        EnumSingleton.otherMethod();

        System.out.println(EnumSingleton.INSTANCE);
        System.out.println(EnumSingleton.INSTANCE);

        //反射破坏单例
//        reflection(HungrySingleton.class);

        //反序列化破坏单例
//        serializable(HungrySingleton.getInstance());

        //Unsafe破坏单例，这种目前预防不了
//        unsafe(HungrySingleton.class);

    }

    private static void unsafe(Class<?> clazz) throws InstantiationException {
        Object o = UnsafeUtils.getUnsafe().allocateInstance(clazz);
        System.out.println("Unsafe创建实例" + o);
    }

    private static void serializable(HungrySingleton instance) throws IOException, ClassNotFoundException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(bos);
        oos.writeObject(instance);
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray()));
        System.out.println("反序列化创建实例" + ois.readObject());

    }

    private static void reflection(Class<?> clazz) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
//        for (Constructor<?> constructor : clazz.getDeclaredConstructors()) {
//            System.out.println(constructor);
//        }
        Constructor<?> constructor = clazz.getDeclaredConstructor();
        constructor.setAccessible(true);
        System.out.println("反射创建实例" + constructor.newInstance());
    }
}
